//headers 
#include<algorithm>
#include<cassert>
#include<cstdio>
#include<deque>
#include<iostream>
#include<list>
#include<map>
#include<numeric>
#include<deque>
#include<queue>
#include<set>
#include<string>
#include<sstream>
#include<stack>
#include<streambuf>
#include<vector>
using namespace std;

//macros
#define LET(x,a) typeof(a) x(a)
#define FOR(i,a,n) for(LET(i,a);i!=n;i++)
#define REP(i,n) FOR(i,0,n)
#define sz size()
#define pb push_back
#define ALL(x) x.begin(),x.end()
#define PRINT(x) REP(_,x.sz) cout<<x[_]<<" "; cout<<endl;
const int INF = (int) 1e8;
#define VI vector<int>
#define VS vector<string>
#define VVI vector< vector<int> >
#define PII pair<int,int>
#define VII vector< PII >
#define LL long long
#define mp make_pair


//code of suren

int summate(VVI &grid){
  int ret = 0 ;
  REP(i,grid.sz) REP(j,grid[i].sz) ret+=grid[i][j];
  return ret;
}

struct edge {
  int cost , loc;
  edge( int a , int b) : cost(a),loc(b){ }
};

bool operator < ( const edge &a, const edge &b ){
  if ( a.cost != b.cost ) return a.cost < b.cost;
  return a.loc < b.loc ;
}

int dijkstra(VVI &grid, int start, int end){
  
  priority_queue<edge> q;
  q.push(edge(start,0));
  VI seen(grid.sz);
  
  while(!q.empty()){
    edge Edge = q.top(); q.pop();
    seen[Edge.loc] = 1 ;
    
    if(Edge.loc == end) return Edge.cost;
    
    REP(i,grid[Edge.loc].sz) if(!seen[i] && grid[Edge.loc][i]) q.push(edge(i,Edge.cost + grid[Edge.loc][i]));
  }

  return 0;
}

int go(VS &graph){
  VVI grid(26,VI(26));
  
  REP(i,graph.sz) grid[ graph[i][0]-'a' ][ graph[i][graph[i].sz-1]-'a' ] = graph[i].sz;
  int start=-1 , end=-1;
  REP(i,grid.sz) { 
    int tot = 0;
    REP(j,grid.sz) if(grid[i][j]) tot++;
    if(tot%2)  if(start==-1) start = i; else end=i;
  }
  int ans;
  ans=summate(grid); 
  if(start!=-1 && end!=-1) ans += dijkstra(grid,end,start);
  return ans;
}


int main(){
  string s; VS graph;
  while(cin>>s){
    if(s!="deadend") graph.pb(s);
    else { int ans = go(graph); graph.clear(); cout<<ans<<endl; }
  }
  return 0;
}
